package com.soundShape.utils
{
	import mx.core.UIComponent;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.geom.Matrix;
	import flash.filters.BlurFilter;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.display.Loader;
	import flash.net.URLRequest;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.system.LoaderContext;
	import flash.display.Graphics;
	import flash.display.Sprite;	
	
	public class ImageProxy extends UIComponent
	{
		private var _s:Sprite;
		private var _image:Bitmap;
		private var _loader:Loader;
		private var _isDirty:Boolean = false;
		
		/*	scaleModes...
				fit - scales to fit the control shows letterbox (default)
				fill - scales to fit the entire control with no letterbox
		*/
		private var _scaleMode:String = "fit";
		
		public function get scaleMode():String {
			return _scaleMode;
		}
		
		public function set scaleMode(value:String): void {
			_scaleMode = value;
		}

		private var _filename:String = "";
		
		public function get filename():String {
			return _filename;
		}
		
		public function set filename(value:String): void {
			_filename = value;
		}		
		
		
		public function ImageProxy() { super(); }
		
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void {
			super.updateDisplayList(unscaledWidth, unscaledHeight);
			

			if(_s) {
				_s.x = (this.width - _s.width)/2;
				_s.y = (this.height - _s.height)/2;
			}
						
			if (_isDirty) {
				_image.x = (this.width - _image.width)/2;
				_image.y = (this.height - _image.height)/2;
				_isDirty = false;
				this.removeChild(_s);
				
			}
		} 
		
		override protected function createChildren(): void {
			super.createChildren();
			
			_s = new Sprite();
			var g:Graphics = _s.graphics;
			
			g.beginFill(0xffffff, .5);
			g.moveTo(10,0)
			g.lineTo(30,0);
			g.lineTo(30,30);
			g.lineTo(40,30);
			g.lineTo(20, 55);
			g.lineTo(0, 30);
			g.lineTo(10,30);
			g.endFill();
			
			addChild(_s);
		}
		
		public function load(): void {
			_loader = new Loader();

			_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoadHandler)
			_loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
			_loader.load(new URLRequest(_filename));
		}
		
		private function imageLoadHandler(e:Event) : void {
			_image = createFilteredBmp(e.target.content.bitmapData, this.width, this.height);
			addChild(_image);
			_isDirty = true;
			invalidateDisplayList();

			//	clean up
			e.target.removeEventListener(Event.COMPLETE, imageLoadHandler)
			e.target.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
			_loader = null;	
		}
		
		private function ioErrorHandler(e:IOErrorEvent) : void {
			trace(e.text);
		}
		
		/*	This function was written by Andi Skater and was found at
			http://www.adobe.com/cfusion/webforums/forum/messageview.cfm?forumid=72&catid=651&threadid=1288553&enterthread=y
		*/
		public function createFilteredBmp(b:BitmapData,newWidth:Number,newHeight:Number):Bitmap {
			var scale:Array = getScaleFactors(b.width,b.height,newWidth,newHeight);
			
			if(scale[0] == 1.0){
				//no scaling
				return new Bitmap(b);
			} else {
				var smoothedBmp:BitmapData;
				var bmpDataImg:BitmapData = b;
				var matrix:Matrix = new Matrix();
				matrix.scale(scale[0], scale[0]);

				if(scale[0] < 1.0){				
					//smooth and scale down
					smoothedBmp = new BitmapData(scale[3],scale[4],true,0x00000000);		
					smoothedBmp.applyFilter(bmpDataImg,new Rectangle(0,0,scale[3],scale[4]),new Point(0,0),new BlurFilter(1/scale[0],1/scale[0],1));
					bmpDataImg.dispose();
				} else{
					// normal scale up
					smoothedBmp = bmpDataImg;
				}
			}
			
			var bmp:BitmapData = new BitmapData(scale[1], scale[2], true, 0x00000000);
			bmp.draw(smoothedBmp, matrix, null, null, null, true);		
			smoothedBmp.dispose();
			
			return new Bitmap(bmp);		
		}

		/*	This function was written by Andi Skater and was found at
			http://www.adobe.com/cfusion/webforums/forum/messageview.cfm?forumid=72&catid=651&threadid=1288553&enterthread=y
		*/		
		[ArrayElementType("Number")]
		private function getScaleFactors(width:Number,height:Number,newWidth:Number,newHeight:Number):Array{
			
			var factorX:Number = newWidth/width
			var factorY:Number = newHeight/height
			var scaleFactor:Number;
			
			if (_scaleMode == "fit") {
				scaleFactor = (factorX < factorY)? factorX:factorY;
			} else {
				scaleFactor = (factorX > factorY)? factorX:factorY;
			}
			var scaledWidth:Number = width * scaleFactor;
			var scaledHeight:Number = height * scaleFactor;
			
			[ArrayElementType("Number")]
			var factors:Array = [scaleFactor,scaledWidth,scaledHeight,width,height]			
			return factors
		}
		
		
	}
}